package org.weso.lodin.appserv;

import java.io.InputStream;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import junit.framework.Assert;

import org.apache.commons.lang3.text.WordUtils;
import org.apache.log4j.Logger;
import org.weso.lodin.dao.DataInformationIndicatorDAOImpl;
import org.weso.lodin.dao.IndicatorDAO;
import org.weso.lodin.dao.IndicatorDAOImpl;
import org.weso.lodin.datasource.config.DatasetTemplateDAO;
import org.weso.lodin.datasource.config.DatasetTemplateDAOImpl;
import org.weso.lodin.generated.Dataset;
import org.weso.lodin.generated.IdIndicator;
import org.weso.lodin.to.DatasetTO;
import org.weso.lodin.to.ProviderTO;
import org.weso.lodin.utils.PrefixManager;

import com.hp.hpl.jena.rdf.model.Model;
import com.hp.hpl.jena.rdf.model.ModelFactory;
import com.hp.hpl.jena.rdf.model.Resource;
import com.hp.hpl.jena.vocabulary.DC;
import com.hp.hpl.jena.vocabulary.DCTerms;
import com.hp.hpl.jena.vocabulary.RDF;
import com.hp.hpl.jena.vocabulary.RDFS;

public class DatasetAppServ {

	private static final String HTTP_WWW_W3_ORG_2006_TIME_INTERVAL_STARTS = "http://www.w3.org/2006/time#intervalStarts";
	private static final String HTTP_WWW_W3_ORG_2006_TIME_INTERVAL_FINISH = "http://www.w3.org/2006/time#intervalFinishes";
	public static final String HTTP_PURL_ORG_LINKED_DATA_CUBE = PrefixManager.getURIPrefix("qb");
	public static final String HTTP_PURL_ORG_LINKED_DATA_SDMX_2009_ATTRIBUTE = PrefixManager.getURIPrefix("sdmx-attribute");
	public static final String WEBINDEX_BASE_URI = PrefixManager.getURIPrefix("wi");
	public static final String LAYER_BASE_URI = PrefixManager.getURIPrefix("wi-layer");	
	public static final String COMPONENT_BASE_URI = PrefixManager.getURIPrefix("wi-component");
	public static final String INDICATOR_BASE_URI = PrefixManager.getURIPrefix("wi-indicator");
	public static final String MEASURE_BASE_URI =  PrefixManager.getURIPrefix("wi-measure");
	public static final String OBSERVATION_BASE_URI =  PrefixManager.getURIPrefix("wi-observation");
	public static final String AREA_BASE_URI =  PrefixManager.getURIPrefix("wi-area");
	public static final String COUNTRY_BASE_URI = PrefixManager.getURIPrefix("wi-country");
	public static final String REGION_BASE_URI = PrefixManager.getURIPrefix("wi-region");
	public static final String ORG_BASE_URI = PrefixManager.getURIPrefix("wi-org");
	public static final String ONTOLOGY_BASE_URI = PrefixManager.getURIPrefix("wi-onto");
	private static final String SKOS = PrefixManager.getURIPrefix("skos");

	

	
	protected static Logger logger = Logger.getLogger(DatasetAppServ.class);
	private Model orgsModel;
	
	public Map<Dataset, Model> transform(){
		Map<Dataset, Model> datasetMap = new HashMap<Dataset, Model>();
		//Data
		ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
		InputStream in = classLoader.getResourceAsStream(TransformerAppServ.WEBINDEX_RAW_DATA_XLS);
		//Indicators		
		DatasetTemplateDAO dao = new DatasetTemplateDAOImpl();		
		List<Dataset> datasets = dao.getDatasets();
		for(Dataset dataset:datasets){			
			datasetMap.put(dataset,datasetAsRDF(dataset));
		}	
	    //Serialize
	    return datasetMap;
	}

	public static Map<String, DatasetTO> getDatasets(InputStream inData) {
		Map<String, DatasetTO> datasetMap = new HashMap<String, DatasetTO>();
		IndicatorDAO dao = new IndicatorDAOImpl(inData);		
		List<DatasetTO> indicators = dao.getSecondaryIndicators();	
		for(DatasetTO indicator:indicators){	
				datasetMap.put(indicator.getCode(),indicator);
		}	
	    return datasetMap;
	}
	
	public static Map<String, DatasetTO> getDatasets(){
		return getDatasets(TransformerAppServ.WEBINDEX_RAW_DATA_XLS);		
	}
	
	public static Map<String, DatasetTO> getDatasets(String rawData){		
		ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
		return getDatasets(classLoader.getResourceAsStream(rawData));		
	}
	
	
	public Map<DatasetTO, Model> transformIndicatorsDAO(){
		InputStream data = Thread.currentThread().getContextClassLoader().
			getResourceAsStream(TransformerAppServ.WEBINDEX_RAW_DATA_XLS);
		IndicatorDAO dao = new DataInformationIndicatorDAOImpl(data);		
		List<DatasetTO> secondaryIndicators = dao.getSecondaryIndicators();
		List<DatasetTO> primaryIndicators = dao.getPrimaryIndicators();//Data
		orgsModel = ModelFactory.createDefaultModel();
		Map<DatasetTO, Model> indicatorMap = new HashMap<DatasetTO, Model>();
		for(DatasetTO indicator:secondaryIndicators){			
			indicatorMap.put(indicator,datasetAsRDF(indicator));
		}	
		for(DatasetTO indicator:primaryIndicators){			
			indicatorMap.put(indicator,datasetAsRDF(indicator));
		}
		//Serialize
	    return indicatorMap;
	}
	
	
	public Model datasetAsRDF(DatasetTO dataset) {
		boolean isPrimary = dataset.getType().equalsIgnoreCase(DataInformationIndicatorDAOImpl.PRIMARY);
		Model model =ModelFactory.createDefaultModel();
		addProperties(model);
		Resource indicatorType = model.createResource(ONTOLOGY_BASE_URI+(isPrimary?"PrimaryIndicator":"SecondaryIndicator"));	
		Resource indicatorResource = model.createResource(INDICATOR_BASE_URI+dataset.getCode());		
		model.add(indicatorResource, RDF.type, indicatorType);
		//Resource indicatorSliceType = model.createResource(HTTP_PURL_ORG_LINKED_DATA_CUBE+"Slice");
		//model.add(indicatorResource, RDF.type, indicatorSliceType);
		model.add(indicatorResource,RDFS.label,TransformerAppServ.literalLang(model,dataset.getIndicator(),TransformerAppServ.LANG_EN));
		model.add(indicatorResource,RDFS.comment,TransformerAppServ.literalLang(model,dataset.getVariableDescription(),TransformerAppServ.LANG_EN));
		if(!isPrimary){
			model.add(indicatorResource,model.createProperty(ONTOLOGY_BASE_URI+"missing-data-notes"),
					TransformerAppServ.literalLang(model,dataset.getMissingNotes(),TransformerAppServ.LANG_EN));
		}
		model.add(indicatorResource,DCTerms.identifier,dataset.getCode());
		model.add(indicatorResource,DCTerms.description,TransformerAppServ.literalLang(model,dataset.getVariableDescription(),TransformerAppServ.LANG_EN));
		model.add(indicatorResource,DCTerms.coverage,dataset.getTimeCoverage());
		model.add(indicatorResource,DCTerms.source,dataset.getUriDataProvider());
		model.add(indicatorResource,model.createProperty(ONTOLOGY_BASE_URI+"high-low"),dataset.getHigh()?getHighResource(model):getLowResource(model));
		if(dataset.getLatestReport()!=null && 
				!dataset.getLatestReport().equalsIgnoreCase("")){
			model.add(indicatorResource,model.createProperty(ONTOLOGY_BASE_URI+"latest-report"),dataset.getLatestReport());
		}
		if(!isPrimary){
			model.add(indicatorResource,model.createProperty(ONTOLOGY_BASE_URI+"data-range"),dataset.getDataRange());
		}
		model.add(indicatorResource,model.createProperty(ONTOLOGY_BASE_URI+"provider-link"),dataset.getUriDataProvider());
		indicatorResource.addProperty(model.createProperty(ONTOLOGY_BASE_URI+"ref-layer"), 
				model.createResource(LAYER_BASE_URI+
						WordUtils.capitalizeFully(dataset.getLayer().trim(), new char[]{' '}).replaceAll(" ", "")));
		
		indicatorResource.addLiteral(model.getProperty(HTTP_WWW_W3_ORG_2006_TIME_INTERVAL_STARTS), 
				extractStartYear(dataset.getTimeCoverage()));
		indicatorResource.addLiteral(model.getProperty(HTTP_WWW_W3_ORG_2006_TIME_INTERVAL_FINISH),
				extractFinishYear(dataset.getTimeCoverage()));
		indicatorResource.addLiteral(model.getProperty(ONTOLOGY_BASE_URI+"country-coverage"),
				Double.valueOf(dataset.getCountryCoverage()).intValue());	
		for(ProviderTO provider:dataset.getSource()){
			String orgCode = provider.getLabel().replaceAll(" ", "");
			Resource org = model.createResource(ORG_BASE_URI+orgCode);		
			model.add(indicatorResource, model.getProperty(ONTOLOGY_BASE_URI+"ref-source"), org);
			//FIXME:extract
			orgsModel.add(org,RDF.type,"http://www.w3.org/ns/org#Organization");
			orgsModel.add(org,RDFS.label,orgCode);
			orgsModel.add(org,DCTerms.identifier,orgCode);
		}
		indicatorResource.addProperty(model.getProperty(SKOS+"broader"), 
				model.createResource(COMPONENT_BASE_URI+
						WordUtils.capitalizeFully(dataset.getComponent().trim(), new char[]{' '}).replaceAll(" ", "")));
		
		return model;
	
	}
	


	private Resource getLowResource(Model m) {
		return m.createResource(ONTOLOGY_BASE_URI+"Low");
	}

	private Resource getHighResource(Model m) {
		return m.createResource(ONTOLOGY_BASE_URI+"High");
	}
	
	private Integer extractStartYear(String timeCoverage) {
		if(timeCoverage.contains(";")){
			String [] values = timeCoverage.split(";");
			return Integer.valueOf(values[0]);
		}else if(timeCoverage.contains("-")){
			return Integer.valueOf(timeCoverage.split("-")[0]);
		}else if (timeCoverage.contains(".")){
			return Integer.valueOf(timeCoverage.split("\\.")[0]);
		}else return 2011;
	}

	private Integer extractFinishYear(String timeCoverage) {
		if(timeCoverage.contains(";")){
			String [] values = timeCoverage.split(";");
			return Integer.valueOf(values[values.length-1]);
		}else if(timeCoverage.contains("-")){
			String yearStr = timeCoverage.split("-")[1];
			Integer year = Integer.valueOf(yearStr)+2000;
			return year;
		}else if (timeCoverage.contains(".")){
			return Integer.valueOf(timeCoverage.split("\\.")[0]);
		}else return 2011;
	}

	public Model datasetAsRDF(Dataset dataset) {
		Model model =ModelFactory.createDefaultModel();
		addProperties(model);
		Resource indicatorType = model.createResource(ONTOLOGY_BASE_URI+"Indicator");
		Resource indicatorResource = model.createResource(INDICATOR_BASE_URI+dataset.getId());
		model.add(indicatorResource, RDF.type, indicatorType);
		
		return model;
	
	}
	

	private void addProperties(Model model) {
		model.createProperty(ONTOLOGY_BASE_URI+"value");
		model.createProperty(ONTOLOGY_BASE_URI+"ref-area");
		model.createProperty(ONTOLOGY_BASE_URI+"ref-source");
		model.createProperty(ONTOLOGY_BASE_URI+"ref-year");
		model.createProperty(ONTOLOGY_BASE_URI+"ref-indicator");
		model.createProperty(ONTOLOGY_BASE_URI+"country-coverage");
		model.createProperty(SKOS+"broader");
		model.createProperty(HTTP_PURL_ORG_LINKED_DATA_SDMX_2009_ATTRIBUTE,"unitMeasure");
		model.createProperty(HTTP_PURL_ORG_LINKED_DATA_CUBE,"dataSet");
		model.createProperty(HTTP_WWW_W3_ORG_2006_TIME_INTERVAL_STARTS);
		model.createProperty(HTTP_WWW_W3_ORG_2006_TIME_INTERVAL_FINISH);
		
		
	}




}
